 /**
 * @author Justin Akin
 * @version Action Pals Core Library 0.1.0
 */
package com.actionpals.utils
{	
	import com.actionpals.enum.Align;
	import com.actionpals.enum.Direction;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.geom.Point;
	
	/**
	 * Position can be used to calculate the alignment of objects.  It is mainly used to layout
	 * groups of objects that all need to be stacked next to one another in one direction.
	 * 
	 */
	public class GlobalPositionUtil
	{
	
	//--------------------------------------------------------------------------------
	//
	//	Public Static Methods
	//
	//--------------------------------------------------------------------------------
		
		public static function stack( target:DisplayObject, stackObj:DisplayObject, direction:String, margin:Number = 0 ):void
		{
			switch( direction )
			{
				case Direction.ABOVE:
				
					stackAbove( target, stackObj, margin );
					break;
					
				case Direction.BELOW:
				
					stackBelow( target, stackObj, margin );
					break;
					
				case Direction.LEFT:
				
					stackLeft( target, stackObj, margin );
					break;
					
				case Direction.RIGHT:
				
					stackRight( target, stackObj, margin );
					break;
			}
		}
		
		public static function stackChildren( parentObj:DisplayObjectContainer, direction:String, margin:Number = 0, index:int = 0 ):void
		{
			var len:int = parentObj.numChildren
			var targetChild:DisplayObject;
			var stackChild:DisplayObject;
			
			index = index <= 0 ? 1 : index;
			
			for( var i:int = index; i < len; i++ )
			{
				targetChild = parentObj.getChildAt( i );
				stackChild = parentObj.getChildAt( i - 1 );
				
				stack( targetChild, stackChild, direction, margin );
			}
		}
		
		public static function align( target:DisplayObject, stackObj:DisplayObject, alignment:String, padding:Number = 0 ):void
		{
			switch( alignment )
			{
				case Align.TOP:
				
					alignTop( target, stackObj, padding );
					break;
					
				case Align.BOTTOM:
				
					alignBottom( target, stackObj, padding );
					break;
					
				case Align.LEFT:
				
					alignLeft( target, stackObj, padding );
					break;
					
				case Align.RIGHT:
				
					alignRight( target, stackObj, padding );
					break;
					
				case Align.VCENTER:
				
					alignVCenter( target, stackObj, padding );
					break;
					
				case Align.HCENTER:
				
					alignHCenter( target, stackObj, padding );
					break;
			}
		}
		
		public static function alignChildren( parentObj:DisplayObjectContainer, alignment:String, padding:Number = 0, index:int = 0 ):void
		{
			var len:int = parentObj.numChildren
			var targetChild:DisplayObject;
			var alignChild:DisplayObject;
			
			index = index <= 0 ? 1 : index;
			
			for( var i:int = index; i < len; i++ )
			{
				targetChild = parentObj.getChildAt( i );
				alignChild = parentObj.getChildAt( i - 1 );
				
				align( targetChild, alignChild, alignment, padding );
			}
		}
		
		public static function stackAbove( target:DisplayObject, stackObj:DisplayObject, margin:Number = 0 ):void
		{
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var s:Point = stackObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( t.x, s.y - target.height - margin ) );
			
			target.y = n.y;
		}
		
		public static function stackBelow( target:DisplayObject, stackObj:DisplayObject, margin:Number = 0 ):void
		{
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var s:Point = stackObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( t.x, s.y + stackObj.height + margin ) );
			
			target.y = n.y;
		}
		
		public static function stackLeft( target:DisplayObject, stackObj:DisplayObject, margin:Number = 0 ):void
		{
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var s:Point = stackObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( s.x - target.width - margin, t.y ) );
			
			target.x = n.x;
		}
		
		public static function stackRight( target:DisplayObject, stackObj:DisplayObject, margin:Number = 0 ):void
		{  
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var s:Point = stackObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( s.x + stackObj.width + margin, t.y ) );
			
			target.x = stackObj.x + stackObj.width + margin;
		}
		
		public static function alignTop( target:DisplayObject, alignObj:DisplayObject, padding:Number = 0 ):void
		{
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var a:Point = alignObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( t.x, a.y + padding ) );
			
			target.y = n.y;
		}
		
		public static function alignBottom( target:DisplayObject, alignObj:DisplayObject, padding:Number = 0 ):void
		{			
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var a:Point = alignObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( t.x, a.y + alignObj.height - target.height - padding ) );
			
			target.y = n.y;
		}
		
		public static function alignLeft( target:DisplayObject, alignObj:DisplayObject, padding:Number = 0 ):void
		{
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var a:Point = alignObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( a.x + padding, t.y ) );
			
			target.x = n.x;
		}
		
		public static function alignRight( target:DisplayObject, alignObj:DisplayObject, padding:Number = 0 ):void
		{
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var a:Point = alignObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( a.x + alignObj.width - target.width - padding, t.y ) );
			
			target.x = n.x;
		}
		
		public static function alignVCenter( target:DisplayObject, alignObj:DisplayObject, offSet:Number = 0 ):void
		{
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var a:Point = alignObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( t.x, a.y + ( ( alignObj.height - target.height ) / 2 ) + offSet ) );
			
			target.y = n.y;
		}
		
		public static function alignHCenter( target:DisplayObject, alignObj:DisplayObject, offSet:Number = 0 ):void
		{
			var t:Point = target.localToGlobal( new Point( 0, 0 ) );
			var a:Point = alignObj.localToGlobal( new Point( 0, 0 ) );
			var n:Point = target.globalToLocal( new Point( a.x + ( ( alignObj.width - target.width ) / 2 ) + offSet, t.y ) );
			
			target.x = n.x;
		}
		
		public static function alignCenter( target:DisplayObject, alignObj:DisplayObject ):void
		{
			alignVCenter( target, alignObj );
			alignHCenter( target, alignObj );
		}
	}
}